package com.smalluz.ad.modules.oe.api.impl;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

import org.apache.commons.lang3.StringUtils;

import com.google.common.collect.ImmutableMap;
import com.smalluz.ad.modules.common.config.MediaConfigStorage;
import com.smalluz.ad.modules.common.enums.GrantType;
import com.smalluz.ad.modules.common.enums.MediaApiUrl;
import com.smalluz.ad.modules.common.exception.ApiException;
import com.smalluz.ad.modules.common.result.BaseResult;
import com.smalluz.ad.modules.common.util.json.JacksonUtils;
import com.smalluz.ad.modules.oe.bean.OAuth2TokenRequest;
import com.smalluz.ad.modules.oe.bean.RefreshTokenRequest;
import com.smalluz.ad.modules.oe.enums.ErrorCodeEnum;
import com.smalluz.ad.modules.oe.result.AccessTokenResult;
import com.smalluz.ad.modules.oe.result.Oauth2AdvertiserResult;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class OeServiceOkHttpImpl extends BaseOeServiceImpl {
 

    @Override
    public String getAccessToken(Boolean forceRefresh) {
        final MediaConfigStorage config = this.getMediaConfigStorage();
        log.info("~~~~token是否有效：{}", config.isAccessTokenValid());

        if (config.isAccessTokenValid() && !forceRefresh) {
            return config.getAccessToken();
        }

        Lock lock = config.getAccessTokenLock();
        boolean locked = false;
        try {
            do {
                locked = lock.tryLock(100, TimeUnit.MILLISECONDS);
                if (!forceRefresh && config.isAccessTokenValid()) {
                    return config.getAccessToken();
                }
                
                log.info("走锁 .....");
            } while (!locked);
        AccessTokenResult acRes = this.getAccessTokenEntity();
        if (acRes != null && acRes.getData() != null && StringUtils.isNoneBlank(acRes.getData().getAccessToken())) {
            return acRes.getData().getAccessToken();
        }

        return "";

        }  catch (Exception e) {
            throw new ApiException(e);
        } finally {
            if (locked) {
                lock.unlock();
            }
        }


    }

    @Override
    public AccessTokenResult getAccessTokenEntity() {
        final MediaConfigStorage config = this.getMediaConfigStorage();
        log.info("~~~~设置的配置参数advertiserId： {}", config.getAdvertiserId());
        log.info("~~~~设置的配置参数appid： {}", config.getAppId());
        log.info("~~~~设置的配置参数secret： {}", config.getSecret());
        log.info("~~~~设置的配置参数authCode： {}", config.getAuthCode());
        String responseContent = "";
        if (StringUtils.isNotBlank(config.getRefreshAccessToken()) && config.isRefreshAccessTokenValid()) {

            log.info("~~~~走刷新参数 refreshToken： {}", config.getRefreshAccessToken());
            responseContent = this.refreshAccessToken();
        } else {
            responseContent = this.getOkHttpUtils().post( MediaApiUrl.OAuth2.OAUTH2_OPEN_API_OAUTH2_ACCESS_TOKEN.getUrl(), OAuth2TokenRequest.builder()
                    .appid(config.getAppId())
                    .secret(config.getSecret())
                    .grantType(GrantType.OceanEngineGrantType.AUTH_CODE.getCode())
                    .authCode(config.getAuthCode())
                    .build().toString());
        }

        log.info("~~~~调用接口返回： {}", responseContent);
        AccessTokenResult acRes = AccessTokenResult.fromJson(Objects.requireNonNull(responseContent));

        return acRes;
    }

    @Override
    public Map<String, MediaConfigStorage> lookMap() {
        return this.getConfigStorageMap();
    }


    @Override
    public String post(MediaApiUrl url, Object object) throws ApiException {
        String responseContent = this.post(null, url.getUrl(), JacksonUtils.bean2Jsn(object));
        BaseResult baseResult = JacksonUtils.jsn2bean(Objects.requireNonNull(responseContent), BaseResult.class);
        //token授权如果已经过期
        if (ErrorCodeEnum.AuthEnum.ACCESS_TOKEN_EXPIRE.getCode().equals(baseResult.getCode())) {
            final MediaConfigStorage config = this.getMediaConfigStorage();
            config.expireAccessToken();
        }
        return responseContent;
    }


    @Override
    public String get(MediaApiUrl url, Object object) throws ApiException {
        String token = this.getAccessToken();
        log.info("~~~调用token：{}", token);
        String responseContent = this.get(token, url.getUrl(), JacksonUtils.bean2Jsn(object));
        BaseResult baseResult = JacksonUtils.jsn2bean(Objects.requireNonNull(responseContent), BaseResult.class);
        //token授权如果已经过期
        if (ErrorCodeEnum.AuthEnum.ACCESS_TOKEN_EXPIRE.getCode().equals(baseResult.getCode())) {
            final MediaConfigStorage config = this.getMediaConfigStorage();
            config.expireAccessToken();
        }
        return responseContent;
    }

    @Override
    public String refreshAccessToken() {
        final MediaConfigStorage config = this.getMediaConfigStorage();

        String requestStr = RefreshTokenRequest.builder()
                .appid(config.getAppId())
                .secret(config.getSecret())
                .refreshToken(config.getRefreshAccessToken())
                .grantType(GrantType.OceanEngineGrantType.REFRESH_TOKEN.getCode())
                .build().toString();

        String responseContent = this.getOkHttpUtils().post(MediaApiUrl.OAuth2.OAUTH2_OPEN_API_REFRESH_ACCESS_TOKEN.getUrl(), requestStr);

        AccessTokenResult accessTokenResult = AccessTokenResult.fromJson(responseContent);

        //更新token存储机制
        config.updateAccessToken(accessTokenResult);
        try {
            //记录刷新token错误的日志
            if (!ErrorCodeEnum.CommonEnum.OK.getCode().equals(accessTokenResult.getCode())) { 
            	
            	
            }
        } catch (Exception e) {

        }


        return responseContent;

    }

    @Override
    public String getAccessToken() {
        return this.getAccessToken(false);
    }

    @Override
    public Oauth2AdvertiserResult getOauth2Advertiser() {
        final MediaConfigStorage config = this.getMediaConfigStorage();
        String responseContent = this.get(MediaApiUrl.OAuth2.OAUTH2_OPEN_API_ADVERTISER_GET, ImmutableMap.builder()
                .put("access_token", this.getAccessToken())
                .put("app_id", config.getAppId())
                .put("secret", config.getSecret())
                .build());

        return Oauth2AdvertiserResult.fromJson(Objects.requireNonNull(responseContent));

    }

}
